#ifndef SYMBOL_H
#define SYMBOL_H
#include <stdbool.h>
#include "lexical.h"
#include "list.h"

#define GEN_NAME_MAX_LEN 	16


typedef struct scope_path {
    int *path;    // 数组
    int path_len; // 数组长度 
}scope_path_t;

typedef struct fun_info {
	struct hlist_node hnode; 
    int err_flag;  // 没有通过语法或语义检查
    symbol_e type; // 返回值的类型

    // 对函数来说没有用,因为定义也可以用 extern, 声明也可以不加 extern
    // 但是，这个 is_ext 是真正的 ext
    bool is_ext;
    bool is_ptr;  // 返回值是不是指针
	char name[MAX_ID_LEN+1]; // 函数名称

    // 指向形参变量列表; 注意，仅仅是指向 list_head 的指针
	struct list_head *para_list_head; 
	int para_len; // 参数个数
	int line_num;  // 函数名字所在的行号，为了报错用
    scope_path_t scope_path; 
} fun_t;

typedef struct var_info{
    struct hlist_node hnode; 
    int index; // 变量编号
    int err_flag;  // 没有通过语法或语义检查
    bool is_ext;
    bool is_ptr;
    bool is_literal;
    bool is_left; // 是左值
    bool is_arr;
    symbol_e type; 
    char name[MAX_ID_LEN+1]; // 变量名称
    scope_path_t scope_path; 
    int size; // 变量的大小  
    int ele_num; // 数组元素个数
    struct list_head arr_init_val; // 数组初始化列表, 对常量无效
    struct var_info *init_val; // 带有初始化, 对常量无效
    union {
		int int_val;
		char char_val;
        char *string_val; // 字符串常量用字符数组存储，指向字符数组的首地址
	};
    int line_num; // 名字所在的行号，为了报错用
	//指向当前变量的指针
	struct var_info *pointed_by; // 对这个指针解引用，得到 var_info 
 
	int offset; // 对于局部变量，参数变量的栈帧偏移; 默认值0为无效值,表示全局变量
	fun_t *fun; // 局部变量所属的函数
}var_t;


void fun_destroy(fun_t *fun);
void fun_params_destroy(struct list_head *head);
void var_destroy(var_t *var);
var_t *new_literal(const void *val, symbol_e type);
var_t *new_var(bool is_ext, symbol_e type, bool is_ptr, 
            const char *name, var_t *init, int line);
var_t *new_arr(bool is_ext, symbol_e type, bool is_ptr, 
            const char *name, int len, int line);
fun_t *new_fun(symbol_e type, bool ptr, const char *name, 
		struct list_head *para_list_head, int line);
bool is_literal_string(var_t *var);
#endif